Android 使用 AIDL 实现进程间通信
转载请注明出处,点击此处 查看更多精彩内容
AIDL
(Android Interface Definition Language) 是一种IDL
语言,用于生成可以在Android
设备上两个进程之间进行进程间通信(IPC
)的代码。
以下的文件创建过程是基于Android Studio。
1. 创建.aidl 文件
该文件结构类似与 Java
中的接口,定义了可用的方法和数据的接口。
右键点击程序包 --> new
--> AIDL
--> AIDL File
创建 IMyAidlInterface.aidl
文件,这时 Android Studio
会自动创建一个和 java
同级的目录 aidl
,并在此目录下生成包和 .aidl
文件。如图:
现在定义一个求和的方法,修改后的 IMyAidlInterface
文件如下:
package ***.***.***;
interface IMyAidlInterface {
int sum(int a, int b);
}
2. 生成 .aidl 文件对应的 .java 文件
通过 Build --> Rebuild Project 重新构建项目生成.aidl文件对应的.java文件,如图所示:
3. 创建共享Service
创建一个 Service
用于和其他进程共享数据和方法
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() {
@Override
public int sum(int a, int b) throws RemoteException {
return a+b;
}
};
}
Stub
是生成 IMyAidlInterface.java
时自动生成的一个抽象内部类,继承自 Binder
。
由于在其他进程中并不能知道这个 Service
的名字,所以启动这个 Service
的时候需要使用隐式的 Intent
,因此需要给 Service
添加过滤器:
<service
android:name=".MyService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.mm.action.aidl" />
</intent-filter>
</service>
然后在启动 Service
的时候使用 com.mm.action.aidl
作为 Action
即可。
4. 启动共享 Service
ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 获取定义的接口
IMyAidlInterface aidlInterface = IMyAidlInterface.Stub.asInterface(service);
try {
// 调用接口中的方法
System.out.println(aidlInterface.sum(100, 3));
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
// 使用bindService启动Service
bindService(new Intent("com.mm.action.aidl"), connection, BIND_AUTO_CREATE);
有了以上的这些配置,就能先运行当前项目测试一下了,如果能正确打印数字的和,则以上配置就没有问题了。
5. 在其他项目中共享 Service
新建一个项目,拷贝上面的 .aidl
文件到项目的同名目录下,然后 Rebuild
一下生成对应的 .java
文件,然后根据上面启动 Service
的方法启动即可。发布应用时,共享 Service
的APK要使用同一个签名,否则无法正常共享。
6. 传递复杂对象
6.1
使用 AIDL
可以直接传递基本数据类型(int
long
float
double
)、String
、List
和 Map
,如果要传递复杂对象,需要使该对象实现 Parcelable
接口,并创建同名的 .aidl
文件。
现在我们创建 Person.aidl
和 Person.java
Person.aidl:
package ***;
parcelable Person;
Person.java :
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by shichaohui on 15/11/4.
*/
public class Person implements Parcelable {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.name);
}
public Person() {
}
protected Person(Parcel in) {
this.name = in.readString();
}
public static final Creator<Person> CREATOR = new Creator<Person>() {
public Person createFromParcel(Parcel source) {
return new Person(source);
}
public Person[] newArray(int size) {
return new Person[size];
}
};
}
6.2
修改 IMyAidlInterface.aidl
,添加一个获取 Person
的方法,修改后的 IMyAidlInterface.aidl
文件:
import com.***.androidtest.Person;
interface IMyAidlInterface {
int sum(int a, int b);
Person getPerson();
}
这里一定要记得 import Person.java
所在的包,不然会构建失败。
6.3
修改 MyService
,实现 getPerson()
方法:
public class MyService extends Service {
...
IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() {
...
@Override
public Person getPerson() throws RemoteException {
Person person = new Person();
person.setName("nammmmme");
return person;
}
};
}
最后就可以和使用 sum()
方法一样使用 getPerson()
方法了。